package com.fowo.api.syncLingxingApi.service.syncImpl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fowo.api.datainterface.util.JsonUtil;
import com.fowo.api.entity.Product;
import com.fowo.api.model.attribute.AttributeVo;
import com.fowo.api.service.impl.AttributeServiceImpl;
import com.fowo.api.syncLingxingApi.entity.*;
import com.fowo.api.syncLingxingApi.entity.TmpSyncLingxingToSpuInfo;
import com.fowo.api.syncLingxingApi.service.SyncBaseService;
import com.fowo.api.syncLingxingApi.service.impl.*;
import com.fowo.api.syncLingxingApi.service.impl.TmpSyncLingxingToSpuInfoServiceImpl;
import com.fowo.api.sys.entity.SysUser;
import com.fowo.api.sys.service.impl.SysUserServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
@Slf4j
@DS("ds24")
public class SyncLxSpuInfoServiceImpl extends SyncBaseService {

    @Resource
    private TmpSyncLingxingToSpuInfoServiceImpl tmpSyncLingxingToSpuInfoService;
    @Resource
    private TmpSyncLingxingToSpuInfoSkuListServiceImpl tmpSyncLingxingToSpuInfoSkuListService;
    @Resource
    private AttributeServiceImpl attributeService;


    @Resource
    private SysUserServiceImpl sysUserService;

    public SyncLxSpuInfoServiceImpl() {
        super("spuInfoUrl", 200);
    }

    @Transactional
    public void mainLoop(JSONObject param) throws Exception {
        long start_time_ms = System.currentTimeMillis();
        log.info("初始化操作, 清空临时表数据.");

        if (!super.initData()) {
            log.error("获取token失败.");
            return;
        }
        if (ObjUtil.isEmpty(this.lxApiToken)) return;
        if (ObjUtil.isEmpty(param)) return;
        // 清空临时表数据
        tmpSyncLingxingToSpuInfoService.deleteAll();
        long block_start_time_ms = System.currentTimeMillis();
        final String key = MapUtil.getStr(param, "key", null);
        final String spu = MapUtil.getStr(param, "spu", null);
        final Long psId = MapUtil.getLong(param, "ps_id", null);
        List<TmpSyncLingxingToSpuList> jsonToList = new ArrayList<>();
        if (StrUtil.isNotEmpty(key)) {
            while (redisUtil.ListSize(key) > 0) {
                CollUtil.addIfAbsent(jsonToList, JsonUtil.getJsonToBean(redisUtil.ListLeftPopStr(key), TmpSyncLingxingToSpuList.class));
            }
        } else if (ObjUtil.isNotEmpty(spu) || ObjUtil.isNotEmpty(psId)) {
            TmpSyncLingxingToSpuList toSpuInfo = new TmpSyncLingxingToSpuList();
            toSpuInfo.setSpu(spu);
            toSpuInfo.setPsId(psId);
            jsonToList.add(toSpuInfo);
        } else {
            return;
        }
        List<TmpSyncLingxingToSpuInfo> tmpProductList = new ArrayList<>();
        //jsonToList = CollUtil.page(1, 20, jsonToList);
        for (TmpSyncLingxingToSpuList jsonToBean : jsonToList) {
            JSONObject results = this.pullLingxingData(jsonToBean.getPsId(), null);
            if (ObjUtil.isNotEmpty(results) && MapUtil.getInt(results, "code") == 0) {
                TmpSyncLingxingToSpuInfo tmpProduct = JsonUtil.getJsonToBean(MapUtil.getStr(results, "data"), TmpSyncLingxingToSpuInfo.class);
                //初始化赋值
                tmpProduct.init();
                tmpProduct.set_version(this.data_version);
                tmpProduct.setId(IdUtil.getSnowflakeNextId());
                // 产品负责人名称处理
                tmpProduct.setProductDutyUsersMirror(this.productDutyUsersMirrorFilter(tmpProduct.getProductDutyUsers()));
                // 产品负责人处理
                tmpProduct.setProductDutyUsers(this.productDutyUsersFilter(tmpProduct.getProductDutyUsers()));
                // 关联辅料处理
                tmpProduct.setAuxRelationListMirror(this.auxRelationListMirrorFilter(tmpProduct, tmpProduct.getSkuList()));
                // 产品列表处理
                tmpProduct.setSkuListMirror(this.skuListMirrorFilter(tmpProduct, tmpProduct.getSkuList()));

                tmpProductList.add(tmpProduct);
            }
        }

        if (CollUtil.isNotEmpty(tmpProductList)) {
            List<Product> oldProducts = searchOldData(tmpProductList.stream().map(TmpSyncLingxingToSpuInfo::getSpu).collect(Collectors.toList()));
            List<TmpSyncLingxingToSpuInfo> cmpResults = compareNewOrOldDataSpu(tmpProductList, oldProducts);
            // 插入临时表
            tmpSyncLingxingToSpuInfoService.saveBatch(cmpResults);
            // 插入属性临时表
            List<TmpSyncLingxingToSpuInfoSkuList> skuList = cmpResults.stream().flatMap(fm -> CollUtil.isEmpty(fm.getSkuListMirror()) ? Stream.empty() : fm.getSkuListMirror().stream()).collect(Collectors.toList());
            tmpSyncLingxingToSpuInfoSkuListService.saveBatch(skuList);
            log.info("插入spu临时表，数量：" + Convert.toStr(cmpResults.size()) + "插入属性临时表，数量：" + Convert.toStr(skuList.size()));
            long currentTimeMillis = System.currentTimeMillis();
            log.info(StrUtil.concat(true, "拉取数据用时", Convert.toStr(currentTimeMillis - block_start_time_ms), "毫秒。总用时", Convert.toStr(currentTimeMillis - start_time_ms), "毫秒"));
        }
        saveTempToFormal();
    }

    private List<TmpSyncLingxingToSpuInfoAuxRelationList> auxRelationListMirrorFilter(TmpSyncLingxingToSpuInfo tmpProduct, String auxRelationList) {
        if (StrUtil.isEmpty(auxRelationList)) {
            return null;
        }
        List<TmpSyncLingxingToSpuInfoAuxRelationList> list = JsonUtil.getJsonToList(auxRelationList, TmpSyncLingxingToSpuInfoAuxRelationList.class);
        if (CollUtil.isEmpty(list)) {
            return null;
        }
        for (TmpSyncLingxingToSpuInfoAuxRelationList item : list) {
            item.init();
            tmpProduct.set_version(this.data_version);
            item.setParentId(tmpProduct.getId());
            item.setAuxId(item.getAuxId());
            item.setAuxName(item.getAuxName());
            item.setAuxSku(item.getAuxSku());
            item.setCgPrice(item.getCgPrice());
            item.setQuantity(item.getQuantity());
            item.setRemark(item.getRemark());
            item.setId(tmpProduct.getId());
            item.setPsId(tmpProduct.getPsId());
            item.setSpu(tmpProduct.getSpu());
        }
        return list;

    }

    private List<TmpSyncLingxingToSpuInfoSkuList> skuListMirrorFilter(TmpSyncLingxingToSpuInfo tmpProduct, String skuList) throws Exception {
        if (StrUtil.isEmpty(skuList)) {
            return null;
        }
        List<TmpSyncLingxingToSpuInfoSkuList> list = JsonUtil.getJsonToList(skuList, TmpSyncLingxingToSpuInfoSkuList.class);
        if (CollUtil.isEmpty(list)) {
            return null;
        }
        for (TmpSyncLingxingToSpuInfoSkuList item : list) {
            item.init();
            item.set_version(this.data_version);
            JSONArray attributeMirrorList = new JSONArray();
            List<JSONObject> attributeList = JsonUtil.getJsonToList(item.getAttribute());//[{"pai_id":"1","pai_name":"A","pa_id":1}] --> {name: "尺码", value: "S"}
            if (CollUtil.isNotEmpty(attributeList)) {
                for (JSONObject i : attributeList) {
                    JSONObject attributeMirror = new JSONObject();
                    AttributeVo paId = attributeService.getVoById(MapUtil.getLong(i, "pa_id"));
                    attributeMirror.put("name", paId.getName());
                    attributeMirror.put("value", MapUtil.getStr(i, "pai_name"));
                    attributeMirrorList.add(attributeMirror);
                }
                //款式属性子表属性赋值
                item.setAttributeMirror(JsonUtil.getObjectToString(attributeMirrorList));
            }
            Product product = productService.getProductBySku(item.getSku());
            if (ObjUtil.isNotEmpty(product)) {
                item.setProductId(product.getId());
                item.setSku(product.getSku());
                item.setProductName(product.getName());
                item.setPicUrlMirror(product.getPicUrl());//todo 使用产品主图,暂不考虑替换
            }
            item.setParentId(tmpProduct.getId());
            item.setPsId(tmpProduct.getPsId());
            item.setSpu(tmpProduct.getSpu());
        }
        return list;
    }

    private String productDutyUsersMirrorFilter(String productDutyUsers) {
        if (StrUtil.isEmpty(productDutyUsers)) {
            return null;
        }
        List<JSONObject> list = JsonUtil.getJsonToList(productDutyUsers, JSONObject.class);
        if (CollUtil.isEmpty(list)) {
            return null;
        }
        List<String> productDutyUserIds = sysUserService.listObjs(Wrappers.<SysUser>lambdaQuery().select(SysUser::getId).in(SysUser::getName, list.stream().map(m -> MapUtil.getStr(m, "realname")).toArray(String[]::new)), s -> Convert.toStr(s));
        return JsonUtil.getObjectToString(productDutyUserIds);
    }

    private String productDutyUsersFilter(String productDutyUsers) {
        if (StrUtil.isEmpty(productDutyUsers)) {
            return null;
        }
        List<JSONObject> list = JsonUtil.getJsonToList(productDutyUsers, JSONObject.class);
        if (CollUtil.isEmpty(list)) {
            return null;
        }
        return JsonUtil.getObjectToString(list.stream().map(m -> MapUtil.getStr(m, "realname")).toArray(String[]::new));
    }


    protected void saveTempToFormal() {
        // 新增产品表
        tmpSyncLingxingToSpuInfoService.insertSpuInfo(this.data_version);
        tmpSyncLingxingToSpuInfoService.insertSpuInfoSkuList(this.data_version);
        tmpSyncLingxingToSpuInfoService.insertSpuInfoAuxRelationList(this.data_version);
    }

    public JSONObject pullLingxingData(Long psId, String spu) {
        Map<String, Object> requestBody = new HashMap<>();
        if (ObjUtil.isNotEmpty(psId)) {
            requestBody.put("ps_id", psId);
        }
        if (ObjUtil.isNotEmpty(spu)) {
            requestBody.put("spu", spu);
        }
        return tryRequestLingxingApi(requestBody, super.lxApiUrl);
    }

    public List<Product> searchOldData(List<String> spus) {
        QueryWrapper<Product> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("spu", spus);
        return productService.list(queryWrapper);
    }


}
